﻿using System.Collections.Generic;
using Framework.GamePool.@abstract;
using Framework.GamePool.config;
using Framework.Utils.SingletonTemplate;
using UnityEngine;
using Object = UnityEngine.Object;

namespace Framework.GamePool.manager
{

    [System.Serializable]
    public struct PoolObject
    {

        public string Table;

        public GamePoolAbstract Poolobject;

        public PoolObject(string table, GamePoolAbstract poolobject)
        {
            this.Table      = table;
            this.Poolobject = poolobject;
        }

    }

    public class GamePoolManager : MgrMonoBase<GamePoolManager>
    {

        public Dictionary<string, GamePoolAbstract> GamePoolDic;

        public List<GamePoolAbstract> GamePoolList;
        public List<GamePoolAbstract> GamePoolDisableList;

        protected override void InitMgr()
        {
            this.GamePoolDic         = new Dictionary<string, GamePoolAbstract>();
            this.GamePoolList        = new List<GamePoolAbstract>();
            this.GamePoolDisableList = new List<GamePoolAbstract>();
        }

        //         /// <summary>
        //         /// 初始化
        //         /// </summary>
        //         public GamePoolManager(GamePoolConfig gamePoolConfig) {
        //
        //
        // //            SetPoolObject(gamePoolConfig);
        //         }

        /// <summary>
        /// 设置对象池预制体
        /// </summary>
        /// <param name="PoolDic"></param>
        public void SetPoolObject(Dictionary<string, GamePoolAbstract> PoolDic, string Group = null)
        {
            foreach (var item in PoolDic.Keys)
            {
                if (!this.GamePoolDic.ContainsKey(item))
                {
                    this.GamePoolDic.Add(item, PoolDic[item]);
                    PoolDic[item].Group = Group;
                }
            }
        }

        public void SetPoolObject(string table, GamePoolAbstract poolObject, string Group = null)
        {
            if (!this.GamePoolDic.ContainsKey(table))
            {
                this.GamePoolDic.Add(table, poolObject);
                poolObject.Group = Group;
            }
        }

        public void SetPoolObject(GamePoolConfig config, string Group = null)
        {
            if (config != null)
            {
                config.PoolList.ForEach(poolObject =>
                {
                    if (!this.GamePoolDic.ContainsKey(poolObject.Table))
                    {
                        this.GamePoolDic.Add(poolObject.Table, poolObject.Poolobject);
                        poolObject.Poolobject.Group = Group;
                    }
                });
            }
        }

        /// <summary>
        /// 查询是否加载了指定标签的对象
        /// </summary>
        /// <param name="ObjectName"></param>
        /// <returns></returns>
        public bool SelectObject(string ObjectName) { return this.GamePoolDic.ContainsKey(ObjectName); }

        public void CheckNullObject()
        {
            for (int i = this.GamePoolList.Count - 1; i >= 0; i--)
            {
                if (this.GamePoolList[i] == null)
                {
                    // Debug.Log("删除对象池对象");
                    this.GamePoolList.RemoveAt(i);
                }
            }
        }

        /// <summary>
        /// 获取场景中所有激活状态下的指定对象
        /// </summary>
        /// <param name="objectName"></param>
        /// <returns></returns>
        public List<GameObject> GetActiveObjectAll(string objectName)
        {
            List<GameObject> gameL = new List<GameObject>();
            this.GamePoolList.ForEach(go =>
            {
                if (go.Table.Equals(objectName))
                {
                    gameL.Add(go.gameObject);
                }
            });
            return gameL;
        }

        public List<T> GetActiveObjectAll<T>(string objectName) where T : UnityEngine.Component
        {
            List<T> gameL = new List<T>();
            this.CheckNullObject();
            this.GamePoolList.ForEach(go =>
            {
                if (go.Table.Equals(objectName))
                {
                    T component = go.GetComponent<T>();
                    if (component != null)
                    {
                        gameL.Add(component);
                    }
                }
            });
            return gameL;
        }

        /// <summary>
        /// 禁用指定table的所有对象
        /// </summary>
        /// <param name="table"></param>
        public void DisableObjectWitchTable(string table)
        {
            this.GamePoolList.ForEach(go =>
            {
                if (go.Table.Equals(table))
                {
                    this.Destroy(go);
                }
            });
        }

        public void DisableObjectWitchGroup(string group)
        {
            List<GamePoolAbstract> abstracts = new List<GamePoolAbstract>();
            foreach (var poolAbstract in this.GamePoolList)
            {
                if (group.Equals(poolAbstract.Group))
                {
                    abstracts.Add(poolAbstract);
                }
            }
            foreach (var poolAbstract in abstracts)
            {
                this.Destroy(poolAbstract);
            }
        }

        /// <summary>
        /// 返回一个激活的对象到指定位置
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="table"></param>
        /// <param name="postion"></param>
        /// <returns></returns>
        public T InstantiatePoolObject<T>(string table, Vector3 postion, Transform parent = null, string group = null) where T : UnityEngine.Component
        {
            if (this.GamePoolDic.ContainsKey(table))
            {
                if (parent == null) parent = this.transform;
                for (int i = 0; i < this.GamePoolDisableList.Count; i++)
                {
                    var poolObject = this.GamePoolDisableList[i];
                    if (poolObject.Table.Equals(table))
                    {
                        if (poolObject.transform.parent != parent)
                        {
                            poolObject.transform.SetParent(parent);
                        }

                        poolObject.transform.localPosition = postion;
                        poolObject.transform.localScale    = Vector3.one;
                        this.GamePoolDisableList.RemoveAt(i);
                        poolObject.Group = group ?? this.GamePoolDic[table].Group;
                        poolObject.Pool_Enable();
                        this.GamePoolList.Add(poolObject);
                        return poolObject.GetComponent<T>();
                    }
                }
                GamePoolAbstract go = GameObject.Instantiate(this.GamePoolDic[table], parent);
                go.transform.localPosition = postion;
                go.transform.localScale = Vector3.one;
                go.Table                   = table;
                go.Group                   = group ?? this.GamePoolDic[table].Group;
                go.Pool_Init();
                go.Pool_Enable();
                this.GamePoolList.Add(go);
                return go.GetComponent<T>();
            }

            var obj = Resources.Load<GamePoolAbstract>(table);
            if (obj != null)
            {
                obj.Table               = table;
                obj.Group               = group;
                this.GamePoolDic[table] = obj;
                return this.InstantiatePoolObject<T>(table, postion, parent);
            }
            Debug.Log("<color=red> 错误的从对象池实例化 </color>");
            return default;
        }

        public T InstantiatePoolObject<T>(string table, Vector3 postion, Quaternion quaternion, Transform parent = null) where T : UnityEngine.Component
        {
            var t = this.InstantiatePoolObject<T>(table, postion, parent);
            t.transform.rotation = quaternion;
            return t;
        }


        public T InstantiatePoolObject<T>(string table, Transform parent = null) where T : UnityEngine.Component { return this.InstantiatePoolObject<T>(table, Vector3.zero, parent); }

        public void Destroy(GamePoolAbstract poolObject)
        {
            if (poolObject == null)
                return;
            if (!poolObject.IsDisable())
            {
                poolObject.Pool_Disable();
                this.GamePoolList.Remove(poolObject);
                this.GamePoolDisableList.Add(poolObject);
            }
        }

        public void KillAll()
        {
            this.CheckNullObject();
            foreach (var poolObject in this.GamePoolList)
            {
                Object.Destroy(poolObject.gameObject);
            }

            foreach (var poolObject in this.GamePoolDisableList)
            {
                Object.Destroy(poolObject.gameObject);
            }

            this.GamePoolList.Clear();
            this.GamePoolDic.Clear();
            this.GamePoolDisableList.Clear();
        }

        public void KillForGroup(string group)
        {
            this.CheckNullObject();
            for (int i = this.GamePoolList.Count - 1; i >= 0; i--)
            {
                if (group.Equals(this.GamePoolList[i].Group))
                {
                    this.GamePoolList[i].Pool_Disable();
                    Object.Destroy(this.GamePoolList[i].gameObject);
                    this.GamePoolList.RemoveAt(i);
                }
            }

            for (int i = this.GamePoolDisableList.Count - 1; i >= 0; i--)
            {
                if (group.Equals(this.GamePoolDisableList[i].Group))
                {
                    Object.Destroy(this.GamePoolDisableList[i].gameObject);
                    this.GamePoolDisableList.RemoveAt(i);
                }
            }

            var list = new List<string>(this.GamePoolDic.Keys);
            for (int i = list.Count - 1; i >= 0; i--)
            {
                if (group.Equals(this.GamePoolDic[list[i]].Group))
                {
                    this.GamePoolDic.Remove(list[i]);
                }
            }
            Resources.UnloadUnusedAssets();
        }

    }
}